package com.powerbank.ordercenter.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.powerbank.common.client.DeviceCenterClient;
import com.powerbank.common.client.PaymentCenterClient;
import com.powerbank.common.client.UserCenterClient;
import com.powerbank.common.dto.CreateOrderRequest;
import com.powerbank.common.dto.DeviceDTO;
import com.powerbank.common.dto.OrderDTO;
import com.powerbank.common.dto.ReturnOrderRequest;
import com.powerbank.common.dto.UserDTO;
import com.powerbank.common.enums.OrderStatus;
import com.powerbank.common.enums.OrderType;
import com.powerbank.common.event.EventPublisher;
import com.powerbank.common.event.order.OrderCreatedEvent;
import com.powerbank.common.event.order.OrderPaidEvent;
import com.powerbank.common.event.order.OrderReturnedEvent;
import com.powerbank.common.exception.BusinessException;
import com.powerbank.common.result.PageResult;
import com.powerbank.common.result.Result;
import com.powerbank.common.utils.OrderNoGenerator;
import com.powerbank.ordercenter.entity.Order;
import com.powerbank.ordercenter.mapper.OrderMapper;
import com.powerbank.ordercenter.service.OrderLogService;
import com.powerbank.ordercenter.service.OrderService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 订单服务实现类
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements OrderService {

    private final OrderMapper orderMapper;
    private final OrderLogService orderLogService;
    private final UserCenterClient userCenterClient;
    private final DeviceCenterClient deviceCenterClient;
    private final PaymentCenterClient paymentCenterClient;
    private final EventPublisher eventPublisher;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result<OrderDTO> createOrder(CreateOrderRequest request) {
        // 验证用户
        Result<UserDTO> userResult = userCenterClient.getUserById(request.getUserId());
        if (!userResult.isSuccess() || userResult.getData() == null) {
            return Result.error("用户不存在");
        }

        // 验证设备
        Result<DeviceDTO> deviceResult = deviceCenterClient.getDeviceById(request.getDeviceId());
        if (!deviceResult.isSuccess() || deviceResult.getData() == null) {
            return Result.error("设备不存在");
        }

        DeviceDTO device = deviceResult.getData();
        if (!"AVAILABLE".equals(device.getStatus())) {
            return Result.error("设备不可用");
        }

        // 检查用户是否有未完成订单
        List<Order> activeOrders = orderMapper.findActiveOrdersByUserId(request.getUserId());
        if (!activeOrders.isEmpty()) {
            return Result.error("您有未完成的订单，请先归还设备");
        }

        // 创建订单
        Order order = new Order();
        order.setOrderNo(OrderNoGenerator.generate("ORD"));
        order.setUserId(request.getUserId());
        order.setDeviceId(request.getDeviceId());
        order.setDeviceCode(device.getDeviceCode());
        order.setOrderType(OrderType.RENTAL);
        order.setOrderStatus(OrderStatus.CREATED);
        order.setStartTime(LocalDateTime.now());
        order.setPlannedReturnTime(request.getPlannedReturnTime());
        order.setFreeDuration(5); // 5分钟免费
        order.setUnitPrice(device.getHourlyRate());
        order.setDepositAmount(device.getDepositAmount());
        order.setOriginalAmount(BigDecimal.ZERO);
        order.setDiscountAmount(BigDecimal.ZERO);
        order.setActualAmount(BigDecimal.ZERO);
        order.setPaymentStatus(0);

        // 保存订单
        save(order);

        // 锁定设备
        deviceCenterClient.lockDevice(request.getDeviceId(), order.getOrderNo());

        // 记录日志
        orderLogService.createLog(order.getId(), order.getOrderNo(), "CREATE", 
                                 null, OrderStatus.CREATED.name(), 
                                 request.getUserId(), "USER", "创建订单");

        // 发送事件
        OrderCreatedEvent event = new OrderCreatedEvent(order.getId(), order.getOrderNo(), 
                                                       order.getUserId(), order.getDeviceId());
        eventPublisher.publishEvent(event);

        OrderDTO orderDTO = convertToDTO(order);
        return Result.success(orderDTO);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result<Void> payOrder(String orderNo, String paymentId) {
        Order order = orderMapper.findByOrderNo(orderNo);
        if (order == null) {
            return Result.error("订单不存在");
        }

        if (order.getOrderStatus() != OrderStatus.CREATED) {
            return Result.error("订单状态不正确");
        }

        // 更新订单状态
        OrderStatus beforeStatus = order.getOrderStatus();
        order.setOrderStatus(OrderStatus.PAID);
        order.setPaymentStatus(1);
        order.setPaymentTime(LocalDateTime.now());
        updateById(order);

        // 记录日志
        orderLogService.createLog(order.getId(), orderNo, "PAYMENT", 
                                 beforeStatus.name(), OrderStatus.PAID.name(), 
                                 order.getUserId(), "USER", "支付订单");

        // 发送事件
        OrderPaidEvent event = new OrderPaidEvent(order.getId(), orderNo, 
                                                 order.getUserId(), order.getDeviceId(), paymentId);
        eventPublisher.publishEvent(event);

        return Result.success();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result<Void> startOrder(String orderNo) {
        Order order = orderMapper.findByOrderNo(orderNo);
        if (order == null) {
            return Result.error("订单不存在");
        }

        if (order.getOrderStatus() != OrderStatus.PAID) {
            return Result.error("订单状态不正确");
        }

        // 更新订单状态
        OrderStatus beforeStatus = order.getOrderStatus();
        order.setOrderStatus(OrderStatus.USING);
        order.setStartTime(LocalDateTime.now());
        updateById(order);

        // 启动设备
        // deviceCenterClient.startDevice(order.getDeviceId(), orderNo);

        // 记录日志
        orderLogService.createLog(order.getId(), orderNo, "START", 
                                 beforeStatus.name(), OrderStatus.USING.name(), 
                                 order.getUserId(), "USER", "开始使用");

        return Result.success();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result<OrderDTO> returnOrder(ReturnOrderRequest request) {
        Order order = orderMapper.findByOrderNo(request.getOrderNo());
        if (order == null) {
            return Result.error("订单不存在");
        }

        if (order.getOrderStatus() != OrderStatus.USING) {
            return Result.error("订单状态不正确");
        }

        // 计算费用
        LocalDateTime now = LocalDateTime.now();
        order.setActualReturnTime(now);
        order.setEndTime(now);

        // 计算总时长（分钟）
        long totalMinutes = ChronoUnit.MINUTES.between(order.getStartTime(), now);
        order.setTotalDuration((int) totalMinutes);

        // 计算计费时长
        int chargedMinutes = Math.max(0, (int) totalMinutes - order.getFreeDuration());
        order.setChargedDuration(chargedMinutes);

        // 计算费用
        BigDecimal totalFee = order.getUnitPrice()
                .multiply(BigDecimal.valueOf(chargedMinutes))
                .divide(BigDecimal.valueOf(60), 2, BigDecimal.ROUND_HALF_UP);

        order.setOriginalAmount(totalFee);
        order.setActualAmount(totalFee);

        // 检查是否超时
        if (now.isAfter(order.getPlannedReturnTime())) {
            long overtimeMinutes = ChronoUnit.MINUTES.between(order.getPlannedReturnTime(), now);
            BigDecimal overtimeFee = BigDecimal.valueOf(overtimeMinutes)
                    .multiply(BigDecimal.valueOf(0.1)); // 超时费0.1元/分钟
            order.setOvertimeFee(overtimeFee);
            order.setActualAmount(order.getActualAmount().add(overtimeFee));
        }

        // 更新订单状态
        OrderStatus beforeStatus = order.getOrderStatus();
        order.setOrderStatus(OrderStatus.RETURNED);
        updateById(order);

        // 停止设备\n        // deviceCenterClient.stopDevice(order.getDeviceId(), request.getOrderNo());

        // 记录日志
        orderLogService.createLog(order.getId(), request.getOrderNo(), "RETURN", 
                                 beforeStatus.name(), OrderStatus.RETURNED.name(), 
                                 order.getUserId(), "USER", "归还设备");

        // 发送事件
        OrderReturnedEvent event = new OrderReturnedEvent(order.getId(), request.getOrderNo(), 
                                                         order.getUserId(), order.getDeviceId(), 
                                                         order.getActualAmount());
        eventPublisher.publishEvent(event);

        OrderDTO orderDTO = convertToDTO(order);
        return Result.success(orderDTO);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result<Void> cancelOrder(String orderNo, String reason) {
        Order order = orderMapper.findByOrderNo(orderNo);
        if (order == null) {
            return Result.error("订单不存在");
        }

        if (order.getOrderStatus() == OrderStatus.USING || 
            order.getOrderStatus() == OrderStatus.RETURNED ||
            order.getOrderStatus() == OrderStatus.COMPLETED) {
            return Result.error("订单已开始使用，无法取消");
        }

        // 更新订单状态
        OrderStatus beforeStatus = order.getOrderStatus();
        order.setOrderStatus(OrderStatus.CANCELLED);
        order.setCancelReason(reason);
        order.setCancelTime(LocalDateTime.now());
        updateById(order);

        // 释放设备
        // deviceCenterClient.unlockDevice(order.getDeviceId(), orderNo);

        // 记录日志
        orderLogService.createLog(order.getId(), orderNo, "CANCEL", 
                                 beforeStatus.name(), OrderStatus.CANCELLED.name(), 
                                 order.getUserId(), "USER", "取消订单：" + reason);

        return Result.success();
    }

    @Override
    public Result<OrderDTO> getOrderByNo(String orderNo) {
        Order order = orderMapper.findByOrderNo(orderNo);
        if (order == null) {
            return Result.error("订单不存在");
        }

        OrderDTO orderDTO = convertToDTO(order);
        return Result.success(orderDTO);
    }

    @Override
    public Result<PageResult<OrderDTO>> getUserOrders(Long userId, Integer page, Integer size) {
        Page<Order> pageParam = new Page<>(page, size);
        LambdaQueryWrapper<Order> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Order::getUserId, userId)
               .orderByDesc(Order::getCreatedTime);

        IPage<Order> orderPage = page(pageParam, wrapper);
        List<OrderDTO> orderDTOs = orderPage.getRecords().stream()
                .map(this::convertToDTO)
                .collect(Collectors.toList());

        PageResult<OrderDTO> pageResult = new PageResult<>();
        pageResult.setRecords(orderDTOs);
        pageResult.setTotal(orderPage.getTotal());
        pageResult.setSize(orderPage.getSize());
        pageResult.setCurrent(orderPage.getCurrent());
        pageResult.setPages(orderPage.getPages());

        return Result.success(pageResult);
    }

    @Override
    public Result<OrderDTO> getCurrentOrderByDevice(Long deviceId) {
        Order order = orderMapper.findCurrentOrderByDeviceId(deviceId);
        if (order == null) {
            return Result.error("设备当前无订单");
        }

        OrderDTO orderDTO = convertToDTO(order);
        return Result.success(orderDTO);
    }

    @Override
    public Result<List<OrderDTO>> getUserActiveOrders(Long userId) {
        List<Order> orders = orderMapper.findActiveOrdersByUserId(userId);
        List<OrderDTO> orderDTOs = orders.stream()
                .map(this::convertToDTO)
                .collect(Collectors.toList());

        return Result.success(orderDTOs);
    }

    @Override
    public void handleOverdueOrders() {
        LocalDateTime now = LocalDateTime.now();
        List<Order> overdueOrders = orderMapper.findOverdueOrders(now);

        for (Order order : overdueOrders) {
            try {
                // 强制归还
                ReturnOrderRequest request = new ReturnOrderRequest();
                request.setOrderNo(order.getOrderNo());
                returnOrder(request);
                
                log.info("处理超时订单：{}", order.getOrderNo());
            } catch (Exception e) {
                log.error("处理超时订单失败：{}", order.getOrderNo(), e);
            }
        }
    }

    @Override
    public void handleUnpaidExpiredOrders() {
        LocalDateTime expireTime = LocalDateTime.now().minusMinutes(30); // 30分钟过期
        List<Order> expiredOrders = orderMapper.findUnpaidExpiredOrders(expireTime);

        for (Order order : expiredOrders) {
            try {
                cancelOrder(order.getOrderNo(), "支付超时自动取消");
                log.info("处理未支付过期订单：{}", order.getOrderNo());
            } catch (Exception e) {
                log.error("处理未支付过期订单失败：{}", order.getOrderNo(), e);
            }
        }
    }

    @Override
    public Result<OrderDTO> calculateOrderFee(String orderNo) {
        Order order = orderMapper.findByOrderNo(orderNo);
        if (order == null) {
            return Result.error("订单不存在");
        }

        if (order.getOrderStatus() != OrderStatus.USING) {
            OrderDTO orderDTO = convertToDTO(order);
            return Result.success(orderDTO);
        }

        // 实时计算费用
        LocalDateTime now = LocalDateTime.now();
        long totalMinutes = ChronoUnit.MINUTES.between(order.getStartTime(), now);
        int chargedMinutes = Math.max(0, (int) totalMinutes - order.getFreeDuration());

        BigDecimal currentFee = order.getUnitPrice()
                .multiply(BigDecimal.valueOf(chargedMinutes))
                .divide(BigDecimal.valueOf(60), 2, BigDecimal.ROUND_HALF_UP);

        Order tempOrder = new Order();
        BeanUtils.copyProperties(order, tempOrder);
        tempOrder.setTotalDuration((int) totalMinutes);
        tempOrder.setChargedDuration(chargedMinutes);
        tempOrder.setOriginalAmount(currentFee);
        tempOrder.setActualAmount(currentFee);

        OrderDTO orderDTO = convertToDTO(tempOrder);
        return Result.success(orderDTO);
    }

    @Override
    public boolean updateOrderStatusInTransaction(Long orderId) {
        // 实现订单状态更新逻辑
        Order order = getById(orderId);
        if (order == null) {
            return false;
        }
        
        // 更新订单状态的逻辑
        // 这里只是一个示例，实际逻辑可能会更复杂
        order.setOrderStatus(OrderStatus.PAID);
        return updateById(order);
    }

    @Override
    public String getOrderStatus(Long orderId) {
        Order order = getById(orderId);
        if (order == null) {
            return null;
        }
        return order.getOrderStatus().name();
    }

    private OrderDTO convertToDTO(Order order) {
        OrderDTO dto = new OrderDTO();
        BeanUtils.copyProperties(order, dto);
        return dto;
    }
}